home *** CD-ROM | disk | FTP | other *** search
/ Amiga CD32 Gamer 22 / CD32 Gamer - 1996 - Issue 22.iso / fli / src / c2p_020.s < prev    next >
Text File  |  1994-11-14  |  7KB  |  309 lines

  1. ; Chunky2Planar algorithm, originally by James McCoull
  2. ; Modified by Peter McGavin for variable size and depth
  3. ; and "dirty list" (hope I didn't slow it down too much)
  4. ;
  5. ;     Cpu only solution
  6. ;    Optimised for 020+fastram
  7. ;    Aim for less than 90ms for 320x200x256 on 14MHz 020
  8.  
  9. ;void __asm c2p_8 (register __a0 UBYTE *chunky_data,
  10. ;                  register __a1 PLANEPTR raster,
  11. ;                  register __a2 UBYTE *dirty_list,
  12. ;                  register __d1 ULONG plsiz,
  13. ;                  register __a5 UBYTE *tmp_buffer);
  14.  
  15. ; a0 -> width*height chunky pixels in fastmem
  16. ; a1 -> contiguous bitplanes in chipmem
  17. ; a2 -> dirty list (1-byte flag for whether each 32 pixel "unit" needs updating)
  18. ; d1 = width*height/8   (width*height must be a multiple of 32)
  19. ; a5 -> width*height tmp buffer in fastmem
  20.  
  21.     ifeq    depth-8
  22.         xdef    _c2p_8_020
  23. _c2p_8_020:
  24.     else
  25.     ifeq    depth-6
  26.         xdef    _c2p_6_020
  27. _c2p_6_020:
  28.     else
  29.     ifeq    depth-4
  30.         xdef    _c2p_4_020
  31. _c2p_4_020:
  32.     else
  33.         fail    "unsupported depth!"
  34.     endc
  35.     endc
  36.     endc
  37.  
  38.  
  39. wordmerge    macro        ; i1 i2 tmp
  40.                 ; \1 \2 \3
  41.         move.l    \2,\3        ;\3 = CD
  42.         move.w    \1,\2        ;\2 = CB
  43.         swap    \2        ;\2 = BC
  44.         move.w    \2,\1        ;\1 = AC
  45.         move.w    \3,\2        ;\2 = BD
  46.         endm
  47.  
  48.  
  49. merge        macro        ; io  in out tmp msk sft
  50.                 ; \1  \2  \3  \4  \5  \6
  51.                 ; \1 = abqr
  52.                 ; \2 = ijyz
  53.         move.l    \5,\3    ; \3 = 0x0x
  54.         move.l    \3,\4    ; \4 = 0x0x
  55.         and.l    \1,\3    ; \3 = 0b0r
  56.         and.l    \2,\4    ; \4 = 0j0z
  57.         eor.l    \3,\1    ; \1 = a0q0
  58.         eor.l    \4,\2    ; \2 = i0y0
  59.         lsr.l    #\6,\2    ; \2 = 0i0y
  60.     ifeq \6-1
  61.         add.l    \3,\3
  62.     else
  63.         lsl.l    #\6,\3    ; \3 = b0r0
  64.     endc
  65.         or.l    \2,\1    ; \1 = aiqy
  66.         or.l    \4,\3    ; \3 = bjrz
  67.         endm
  68.  
  69. merge4        macro        ; io  in out tmp msk
  70.                 ; \1  \2  \3  \4  \5
  71.                 ; \1 = abqr
  72.                 ; \2 = ijyz
  73.     ifgt depth-4
  74.         move.l    \5,\3    ; \3 = 0x0x
  75.         move.l    \3,\4    ; \4 = 0x0x
  76.         and.l    \1,\3    ; \3 = 0b0r
  77.         and.l    \2,\4    ; \4 = 0j0z
  78.         eor.l    \3,\1    ; \1 = a0q0
  79.         eor.l    \4,\2    ; \2 = i0y0
  80.         lsr.l    #4,\2    ; \2 = 0i0y
  81.         or.l    \2,\1    ; \1 = aiqy
  82.         move.l    \1,(a5)+    ; write to tmp buffer
  83.         lsl.l    #4,\3    ; \3 = b0r0
  84.         or.l    \4,\3    ; \3 = bjrz
  85.         move.l    \3,(a5)+    ; write to tmp buffer
  86.     else
  87.         move.l    \5,\3    ; this version returns only 1 result
  88.         and.l    \3,\2    ; \2 = 0j0z
  89.         and.l    \1,\3    ; \3 = 0b0r
  90.         lsl.l    #4,\3    ; \3 = b0r0
  91.         or.l    \2,\3    ; \3 = bjrz
  92.         move.l    \3,(a5)+    ; write to tmp buffer
  93.     endc
  94.         endm
  95.  
  96. merge1        macro        ; io  in out tmp msk flg
  97.                 ; \1  \2  \3  \4  \5  \6
  98.                 ; \1 = abqr
  99.                 ; \2 = ijyz
  100.         move.l    \5,\3    ; \3 = 0x0x
  101.         move.l    \3,\4    ; \4 = 0x0x
  102.         and.l    \1,\3    ; \3 = 0b0r
  103.         and.l    \2,\4    ; \4 = 0j0z
  104.         eor.l    \3,\1    ; \1 = a0q0
  105.         eor.l    \4,\2    ; \2 = i0y0
  106.         lsr.l    #1,\2    ; \2 = 0i0y
  107.         or.l    \2,\1    ; \1 = aiqy
  108.         move.l    \1,(a2)        ; write to output plane
  109.         suba.l    a5,a2        ; -plsiz
  110.         add.l    \3,\3    ; \3 = b0r0
  111.         or.l    \4,\3    ; \3 = bjrz
  112.     ifne \6
  113.         move.l    \3,(a2)        ; write to output plane
  114.         suba.l    a5,a2        ; -plsiz
  115.     endc
  116.         endm
  117.  
  118.  
  119. start:        jmp    next        ; self-modified code here
  120. next:        movem.l    d1/a0-a1/a6,-(sp)
  121.  
  122. ; Relocate c2p so that firstsweep2 is at a quad-longword-aligned address.
  123. ; Firstsweep2 loop doesn't fit in '020/'030 cache unless it is exactly aligned.
  124. ; Speed penalty of misalignment is about 30%.
  125.  
  126.         lea    (firstsweep2,pc),a0
  127.         move.l    a0,d0
  128.         and.w    #%00001111,d0    ; relocate by -d0.w bytes
  129.  
  130.         lea    (c2p,pc),a0    ; a0 = src
  131.         movea.l    a0,a1
  132.         sub.w    d0,a1        ; a1 = dst
  133.  
  134.         move.l    a1,start+2    ; patch jmp
  135.  
  136.         move.w    #(end-c2p)/2-1,d0
  137. loop:        move.w    (a0)+,(a1)+    ; relocate code loop
  138.         dbra    d0,loop
  139.  
  140.         move.l    (4).w,a6    ; flush cache
  141.         jsr    (_LVOCacheClearU,a6)
  142.  
  143.         movem.l    (sp)+,d1/a0-a1/a6
  144.         bra.b    start        ; restart
  145.  
  146.         ds.w    8        ; space for relocation of c2p routine
  147.  
  148. ; the real c2p routine starts here
  149. c2p:
  150.         movem.l    d2-d7/a2-a6,-(sp)
  151.  
  152.         sub.w    #24,sp        ; space for temporary variables
  153.  
  154. ; a0 = chunky buffer
  155. ; a1 = output area
  156. ; a2 = dirty list
  157. ; d1 = plsiz
  158. ; a5 = tmp buffer
  159.  
  160.         move.l    a1,(4,sp)    ; save output address
  161.         move.l    a2,(8,sp)    ; save dirty list ptr
  162.         move.l    d1,(12,sp)    ; save plsiz
  163.         lsl.l    #3,d1
  164.         movea.l    a0,a1
  165.         adda.l    d1,a1        ; a1 -> end of chunky buffer
  166.         sub.l    (12,sp),d1
  167.     ifle depth-6
  168.         sub.l    (12,sp),d1
  169.         sub.l    (12,sp),d1
  170.     endc
  171.     ifle depth-4
  172.         sub.l    (12,sp),d1
  173.         sub.l    (12,sp),d1
  174.     endc
  175.         move.l    d1,(16,sp)    ; save 7*plsiz (or 5*plsiz) (or 3*plsiz)
  176.         move.l    a5,(20,sp)    ; save tmp buffer address
  177.  
  178. ;; Sweep thru the whole chunky data once,
  179. ;; Performing 3 merge operations on it.
  180.  
  181.         move.l    #$00ff00ff,a3    ; load byte merge mask
  182.         move.l    #$0f0f0f0f,a4    ; load nibble merge mask
  183.  
  184. ; pass 1
  185. firstsweep:    tst.b    (a2)+        ; does next 32 pixel unit need updating?
  186.         bne.b    firstsweep3
  187.  
  188.         adda.w    #32,a0        ; skip 32 pixels on input/output
  189.  
  190.         cmpa.l    a0,a1
  191.         bne.b    firstsweep
  192.         bra.w    exit        ; exit if no changes
  193.  
  194. ; this becomes the first sweep's main loop after the first change is found
  195. firstsweep2:    tst.b    (a2)+        ; does next 32 pixel unit need updating?
  196.         bne.b    firstsweep3
  197.  
  198.         adda.w    #32,a0        ; skip 32 pixels on input
  199.  
  200.         cmpa.l    a0,a1
  201.         bne.b    firstsweep2
  202.         bra.w    secondsweep    ; on to second sweep if changes
  203.  
  204. firstsweep3:
  205.         movem.l    (a0)+,d0-d7    ; get 32 pixels in registers
  206. ; d0-7 = abcd efgh ijkl mnop qrst uvwx yzAB CDEF
  207.  
  208.         wordmerge    d0,d4,a6    ;d0/4 = abqr cdst
  209.         wordmerge    d1,d5,a6    ;d1/5 = efuv ghwx
  210.         wordmerge    d2,d6,a6    ;d2/6 = ijyz klAB
  211.         wordmerge    d3,d7,a6     ;d3/7 = mnCD opEF
  212.  
  213. ; temporarily save off some registers
  214.         movea.l    d7,a6
  215.         move.l    d6,(sp)
  216.  
  217. ; pass 2
  218.         merge    d0,d2,d6,d7,a3,8    ;d0/d6 = aiqy bjrz
  219.         merge    d1,d3,d7,d2,a3,8    ;d1/d7 = emuc fnvD
  220.  
  221. ; pass 3
  222.         merge4    d0,d1,d2,d3,a4,4    ;d0/d2  = ae74... ae30...
  223.         merge4    d6,d7,d3,d1,a4,4    ;d6/d3  = bf74... bf30...
  224.  
  225. ; bring them back
  226.         move.l    a6,d7
  227.         move.l    (sp),d6
  228.  
  229. ; pass 2
  230.         merge    d4,d6,d0,d1,a3,8    ;d4/d0 = cksA dltB
  231.         merge    d5,d7,d1,d6,a3,8    ;d5/d1 = gowE hpxF
  232.  
  233. ; pass 3
  234.         merge4    d4,d5,d6,d7,a4,4    ;d4/d6 = cg74.. cg30..
  235.         merge4    d0,d1,d7,d5,a4,4    ;d0/d7 = dh74.. dh30..
  236.  
  237.         cmpa.l    a0,a1
  238.         bne.w    firstsweep2        ; end of firstsweep, 250 bytes
  239.                         ; only just fits in instr cache
  240.  
  241. ; (a0)     ae74.. ae30.. bf74.. bf30.. cg74.. cg30.. dh74.. dh30..
  242.  
  243. secondsweep:
  244.         movea.l    a5,a1            ; a1 -> end of tmp buffer
  245.         movea.l    (4,sp),a2        ; a2 -> plane0
  246.         movea.l    (8,sp),a6        ; a6 -> dirty list
  247.         movea.l    (12,sp),a5        ; a5 = plsiz
  248.         adda.l    (16,sp),a2        ; a2 -> plane7
  249.         movea.l    (20,sp),a0        ; a0 -> tmp buffer
  250.  
  251.         movea.l    #$33333333,a3
  252.         movea.l    #$55555555,a4
  253.  
  254.         bra.b    secondsweep2
  255.  
  256. secondsweep3:    addq.l    #4,a2        ; skip 32 pixels on output
  257.  
  258. secondsweep2:    tst.b    (a6)+        ; does next 32 pixel unit need updating?
  259.         beq.b    secondsweep3
  260.  
  261.     ifgt depth-4
  262.  
  263.         movem.l    (a0)+,d0-d6        ; read tmp buffer, not d7 yet
  264.  
  265. ; save d5 temporarily
  266.         move.l    d5,(sp)
  267.  
  268. ;; pass 4
  269.         merge    d0,d4,d5,d7,a3,2    ; d0/d5 = aceg76.. aceg54..
  270.         merge    d2,d6,d7,d4,a3,2    ; d2/d7 = bdhf76.. bdhf54..
  271.  
  272. ;; pass 5
  273.     ifgt depth-6
  274.         merge1    d0,d2,d4,d6,a4,1    ; d0/d4 = abcd7... abcd6...
  275.     endc
  276.         merge1    d5,d7,d6,d2,a4,1    ; d5/d6 = abcd5... abcd4...
  277.  
  278.  
  279. ; restore d5 and finally get d7
  280.         move.l    (sp),d5
  281.         move.l    (a0)+,d7
  282.  
  283.     else
  284.  
  285.         movem.l    (a0)+,d1/d3/d5/d7    ; read tmp buf, depth 4 version
  286.  
  287.     endc
  288.  
  289. ;; pass 4
  290.         merge    d1,d5,d4,d6,a3,2    ; d1/d4 = aceg32.. aceg10..
  291.         merge    d3,d7,d6,d5,a3,2    ; d3/d6 = bdhf32.. bdhf10..
  292.  
  293. ;; pass 5
  294.         merge1    d1,d3,d5,d7,a4,1    ; d1/d5 = abcd3... abcd2...
  295.         merge1    d4,d6,d7,d3,a4,0    ; d4/d7 = abcd1... abcd0...
  296.  
  297.         move.l    d7,(a2)+        ; plane 0
  298.         adda.l    (16,sp),a2        ; +7*plsiz (or 5*plsiz) (or 3*plsiz)
  299.  
  300.         cmp.l    a0,a1
  301.         bne.w    secondsweep2        ; end of secondsweep, 216 bytes
  302.  
  303. exit:
  304.         add.w    #24,sp
  305.         movem.l    (sp)+,d2-d7/a2-a6
  306.         rts
  307. end:
  308.         end
  309.